﻿using System;
using System.AddIn.Hosting;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using dotSimpl.wlanner.Logic;
using HostActorView;
using System.Collections.Generic;
using System.Windows.Documents;

namespace dotSimpl.wlanner
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        #region Fields

        private ConnectionWatcher watcher;
        private SettingsStorage settingsStorage;

        private delegate void NetworkStatusChangeHandler(string ssid, string connection, Guid guid);
        private NetworkStatusChangeHandler connectedHandler;
        private NetworkStatusChangeHandler disconnectedHandler;

        private const string connectEventName = "__connect";
        private const string disconnectEventName = "__disconnect";
        private const string defaultProfile = "__default";
        private const string filePath = "profiles.xml";

        System.Windows.Forms.NotifyIcon trayIcon;

        Collection<AddInToken> actorAddIns;

        #endregion

        #region Constructor

        public Window1()
        {
            InitializeComponent();

            string addInsDirectory = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath);
            //searching for add-ins.
            AddInStore.Rebuild(addInsDirectory);
            actorAddIns = AddInStore.FindAddIns(typeof(ActorView), addInsDirectory);

            //unitTest
#if DEBUG
            MessageBox.Show("UT");
            wlanner.UnitTests.SettingsStorageTest.RunTest();
#endif

            //set-up tray icon.
            trayIcon = new System.Windows.Forms.NotifyIcon();
            trayIcon.Click += new EventHandler(trayIcon_Click);
            trayIcon.Icon = new System.Drawing.Icon("tray.ico");
            trayIcon.Visible = true;

            if (File.Exists(filePath))
            {
                settingsStorage = new SettingsStorage(filePath);
            }
            else
            {
                settingsStorage = CreateSettingsWithDefaultActions();
            }

            connectedHandler = OnWLanConnection;
            disconnectedHandler = OnWLanDisconnection;

            watcher = new ConnectionWatcher();
            watcher.NetworkConnected += new EventHandler<ConnectionStateChangedEventArgs>(watcher_NetworkConnected);
            watcher.NetworkDisconnected += new EventHandler<ConnectionStateChangedEventArgs>(watcher_NetworkDisconnected);
            watcher.StartWatching();
        }

        private SettingsStorage CreateSettingsWithDefaultActions()
        {
            SettingsStorage result = new SettingsStorage();

            foreach (AddInToken addIn in actorAddIns)
            {
                ActorView currentActor = addIn.Activate<ActorView>(AddInSecurityLevel.Host);
                string currentPath = SettingsStorage.CreatePath(connectEventName, defaultProfile, currentActor.InternalName, currentActor.CompatibilityVersion);
                KeyValuePair<string, string>[] settings = currentActor.GetInitialSettins();
                for (int i = 0; i < settings.Length; i++)
                {
                    string path = SettingsStorage.CreatePath(currentPath, settings[i].Key);
                    result.Store(path, settings[i].Value, true);
                }
            }

            return result;
        }

        #endregion

        void trayIcon_Click(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = WindowState.Normal;
        }

        private void OnWLanConnection(string ssid, string connection, Guid guid)
        {
            if (settingsStorage.PathExists(SettingsStorage.CreatePath(connectEventName, ssid)))
            {
                SetSettings(ssid, guid);
            }
            else if (settingsStorage.PathExists(SettingsStorage.CreatePath(connectEventName, defaultProfile)))
            {
                SetSettings(defaultProfile, guid);
            }

            //if (ssid.Equals("forEEE"))
            //{
            //    NetworkInterfaceSettingsHelper.SetIP(guid, "192.168.0.221", "255.255.255.0", "192.168.0.1", "192.168.0.1");
            //    ProxySettingsHelper.UnsetProxy();
            //}
            //else if (ssid.Equals("wifi254"))
            //{
            //    NetworkInterfaceSettingsHelper.SetDHCP(guid);
            //    ProxySettingsHelper.SetProxy("90.0.2.135:3128");
            //}

            PopUp.Show(3000, String.Format("{0} connected to {1}", connection, ssid));
        }

        private void SetSettings(string ssid, Guid guid)
        {
            foreach (AddInToken t in actorAddIns)
            {
                ActorView av = t.Activate<ActorView>(AddInSecurityLevel.Host);
                string[] sNames = av.GetSettingNames();
                List<KeyValuePair<string, string>> settigns = new List<KeyValuePair<string, string>>();

                for (int i = 0; i < sNames.Length; i++)
                {
                    settigns.Add(new KeyValuePair<string, string>(sNames[i], settingsStorage.Get(
                        SettingsStorage.CreatePath(connectEventName, ssid, av.InternalName, av.CompatibilityVersion, sNames[i]))));
                }

                av.ApplySettings(settigns.ToArray(), guid);
            }
        }

        private void OnWLanDisconnection(string ssid, string connection, Guid guid)
        {
            PopUp.Show(3000, String.Format("{0} disconnected from {1}", connection, ssid));
        }

        void watcher_NetworkDisconnected(object sender, ConnectionStateChangedEventArgs e)
        {
            Dispatcher.Invoke(disconnectedHandler, e.NetworkSSID, e.ConnectionName, e.ConnectionGuid);
        }

        void watcher_NetworkConnected(object sender, ConnectionStateChangedEventArgs e)
        {
            Dispatcher.Invoke(connectedHandler, e.NetworkSSID, e.ConnectionName, e.ConnectionGuid);
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            settingsStorage.Save(filePath);
        }

        private void Window_StateChanged(object sender, EventArgs e)
        {
            if (WindowState == WindowState.Minimized)
            {
                Hide();
            }
        }
    }
}
